POV-Ray : Newsgroups : povray.advanced-users : Height-field (dis)orientation : Re: Height-field (dis)orientation Server Time
28 Jul 2024 18:15:38 EDT (-0400)
  Re: Height-field (dis)orientation  
From: Mike Williams
Date: 21 Jul 2004 16:45:26
Message: <XKHGtAAeWt$AFwQx@econym.demon.co.uk>
Wasn't it David Wallace who wrote:
>I am trying to place a relatively flat object on a heightfield using the
>following macros:
>
>#declare Ground = height_field {
> png "lakeb.png"
> smooth
> translate <-.5,-.5,-.5>
> texture { texGnd }
> scale <1e4, 160, 1e4>
>}
>
>#macro trnGnd( ob, ang, px, py, alt)
> rotate y*ang
> #local nrm = <0,0,0>;
> #local ps = trace( ob, <px, 1e5, py>, -y, nrm);
> #if (vlength(nrm)>.1)
>  Reorient(y,nrm)
> #end
> translate ps+nrm*alt
>#end
>
>// Coral is a parametric snake surface
>object { Coral scale 1.0 trnGnd(Ground, -96, 216, -910, 0.45) }
>
>The snake is rather long but lies relatively flat on a plane.  When I try to
>orient the snake so that is is level to the local surface, it fails
>miserably.  Some of it is above the surface and some is below.  What am I
>doing wrong?


There are several things that you could be doing wrong, but my guess is
that your height_field has roughness on a scale that smooth isn't
ironing out.

If you have a small image as your height_field, then smooth will
generally tend to iron out single-pixel bumps, but if you're using a
large image such bumps can seriously perturb the normals.

When you use trace() to get the normal, it might hit a point that's on
the side of a tiny bump and the normal you get shows the shape of the
bump at that exact point, rather than the overall shape of the surface.
Another trace() performed nearby might just miss the bump and return a
normal that points in a completely different direction.

I'd suggest that you try planting cylinders to show you the normals,
like

#macro NormTest(ob,X,Z)
 #local nrm = <0,0,0>;
 #local ps = trace( ob, <X, 1e5, Z>, -y, nrm);
 cylinder {ps, ps+nrm*1000, 50 pigment {rgb x}}
#end

NormTest(Ground,-96,216)

And then try calculating an "average" normal by using four nearby
points, like

#macro NormTest2(ob,X,Z,delta)
 #local A = trace( ob, <X + delta , 1e5, Z>, -y); 
 #local B = trace( ob, <X - delta , 1e5, Z>, -y); 
 #local C = trace( ob, <X , 1e5, Z + delta>, -y); 
 #local D = trace( ob, <X , 1e5, Z - delta>, -y); 
 #local nrm = vnormalize(vcross(A-B,D-C));
 #local ps = trace( ob, <X, 1e5, Z>, -y);
 cylinder {ps, ps+nrm*1000, 50 pigment {rgb y}}
#end
 
NormTest2(Ground,-96,216,100)

where "delta" is chosen to be large enough to smooth out the roughness
of the surface, but not so large that it ignores the actual features of
the landscape that you're trying to follow. (The length of your "Coral"
object might be a suitable value to try.)


-- 
Mike Williams
Gentleman of Leisure


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.